package com.opennews.openplatform.service;

import com.opennews.openplatform.jooq.DSLContextWrapper;
import lombok.RequiredArgsConstructor;
import org.jooq.DSLContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

import static com.opennews.openplatform.entity.Tables.*;

@RequiredArgsConstructor
@Service
public class AccountGroupUserService {
    private final DSLContext dslContext;
    private final DSLContextWrapper dslContextWrapper;
    private final UserService userService;
    private final UserActiveTokenService userActiveTokenService;

    public List<Map<String, Object>> queryAvailableAccountGroups(String userId) {
        List<String> accountGroupIds = dslContext.selectFrom(ACCOUNT_GROUP_USER)
                .where(ACCOUNT_GROUP_USER.USER_ID.eq(userId))
                .fetch(ACCOUNT_GROUP_USER.ACCOUNT_GROUP_ID);

        return dslContext.select(
                        ACCOUNT_GROUP_USER.USER_ID.as("id"),
                        ACCOUNT_GROUP_USER.ACCOUNT_GROUP_ID.as("accountGroupId"),
                        USER.USERNAME.as("username"),
                        USER.FULL_NAME.as("fullName"),
                        USER.AVATAR_FILENAME.as("avatarFilename")
                )
                .from(ACCOUNT_GROUP_USER)
                .join(USER).on(ACCOUNT_GROUP_USER.USER_ID.eq(USER.ID))
                .where(
                        ACCOUNT_GROUP_USER.ACCOUNT_GROUP_ID.in(accountGroupIds)
                                .and(ACCOUNT_GROUP_USER.IS_ACCOUNT_GROUP_CREATOR.isTrue())
                )
                .orderBy(USER.FULL_NAME.asc())
                .fetch()
                .map(p -> Map.of(
                        "id", p.get("accountGroupId"),
                        "isOwner", p.get("id").equals(userId),
                        "ownerId", p.get("id"),
                        "ownerUsername", p.get("username"),
                        "ownerFullName", p.get("fullName"),
                        "ownerAvatarUrl", userService.getAvatarUrl((String) p.get("avatarFilename"))
                ));
    }

    @Transactional
    public void remove(String accountGroupId, String userId, String username) {
        // Removes user from this account group.
        dslContext.deleteFrom(ACCOUNT_GROUP_USER)
                .where(
                        ACCOUNT_GROUP_USER.ACCOUNT_GROUP_ID.eq(accountGroupId)
                                .and(ACCOUNT_GROUP_USER.USER_ID.eq(userId))
                                .and(ACCOUNT_GROUP_USER.IS_ACCOUNT_GROUP_CREATOR.isFalse())
                )
                .execute();

        // Removes user roles in this account group.
        dslContext.deleteFrom(USER_ROLE)
                .where(
                        USER_ROLE.ACCOUNT_GROUP_ID.eq(accountGroupId)
                                .and(USER_ROLE.USER_ID.eq(userId))
                )
                .execute();

        // Checks if this is user's default account group.
        if (dslContextWrapper.count(USER, USER.ID.eq(userId)
                .and(USER.ACCOUNT_GROUP_ID.eq(accountGroupId))) > 0) {
            // Sets user's own account group as default.
            userService.restoreAccountGroupByUserId(userId);

            // Deletes all tokens related to this account group to force a re-login.
            userActiveTokenService.deleteByUserAndAccountGroup(username, accountGroupId);
        }
    }
}
